import { MCPServerInstance } from './mcpManager';

/**
 * MCP服务器错误类型
 */
export enum MCPErrorType {
  STARTUP_FAILED = 'startup_failed',
  TOOL_TIMEOUT = 'tool_timeout',
  TOOL_EXECUTION_ERROR = 'tool_execution_error',
  PROCESS_CRASHED = 'process_crashed',
  COMMUNICATION_ERROR = 'communication_error',
  RESOURCE_EXHAUSTED = 'resource_exhausted'
}

/**
 * MCP错误信息
 */
export interface MCPError {
  type: MCPErrorType;
  serverId: string;
  message: string;
  timestamp: Date;
  retryCount?: number;
  originalError?: Error;
}

/**
 * 重试策略配置
 */
export interface RetryConfig {
  maxRetries: number;
  baseDelay: number; // 基础延迟（毫秒）
  maxDelay: number; // 最大延迟（毫秒）
  backoffMultiplier: number; // 退避倍数
}

/**
 * MCP错误处理器 - 处理各种MCP相关错误和故障恢复
 */
export class MCPErrorHandler {
  private errorHistory: Map<string, MCPError[]> = new Map();
  private retrySchedules: Map<string, NodeJS.Timeout> = new Map();
  private errorListeners: Array<(error: MCPError) => void> = [];

  private readonly defaultRetryConfig: RetryConfig = {
    maxRetries: 3,
    baseDelay: 1000,
    maxDelay: 30000,
    backoffMultiplier: 2
  };

  /**
   * 添加错误监听器
   */
  addErrorListener(listener: (error: MCPError) => void): () => void {
    this.errorListeners.push(listener);
    return () => {
      const index = this.errorListeners.indexOf(listener);
      if (index > -1) {
        this.errorListeners.splice(index, 1);
      }
    };
  }

  /**
   * 处理MCP服务器错误
   */
  async handleError(
    error: MCPError,
    server: MCPServerInstance,
    retryCallback?: () => Promise<void>
  ): Promise<void> {
    // 记录错误历史
    this.recordError(error);

    // 通知监听器
    this.notifyErrorListeners(error);

    // 根据错误类型执行相应的处理策略
    switch (error.type) {
      case MCPErrorType.STARTUP_FAILED:
        await this.handleStartupFailure(error, server, retryCallback);
        break;
      case MCPErrorType.TOOL_TIMEOUT:
        await this.handleToolTimeout(error, server);
        break;
      case MCPErrorType.TOOL_EXECUTION_ERROR:
        await this.handleToolExecutionError(error, server);
        break;
      case MCPErrorType.PROCESS_CRASHED:
        await this.handleProcessCrash(error, server, retryCallback);
        break;
      case MCPErrorType.COMMUNICATION_ERROR:
        await this.handleCommunicationError(error, server, retryCallback);
        break;
      case MCPErrorType.RESOURCE_EXHAUSTED:
        await this.handleResourceExhaustion(error, server);
        break;
      default:
        console.warn(`未知的MCP错误类型: ${error.type}`);
    }
  }

  /**
   * 处理启动失败
   */
  private async handleStartupFailure(
    error: MCPError,
    server: MCPServerInstance,
    retryCallback?: () => Promise<void>
  ): Promise<void> {
    const retryCount = this.getRetryCount(error.serverId);
    
    if (retryCount < this.defaultRetryConfig.maxRetries && retryCallback) {
      const delay = this.calculateRetryDelay(retryCount);
      console.log(`MCP服务器 ${error.serverId} 启动失败，${delay}ms后重试 (${retryCount + 1}/${this.defaultRetryConfig.maxRetries})`);
      
      this.scheduleRetry(error.serverId, delay, async () => {
        error.retryCount = retryCount + 1;
        await retryCallback();
      });
    } else {
      console.error(`MCP服务器 ${error.serverId} 启动失败，已达到最大重试次数`);
      server.status = 'error';
      server.error = `启动失败: ${error.message}`;
    }
  }

  /**
   * 处理工具超时
   */
  private async handleToolTimeout(
    error: MCPError,
    server: MCPServerInstance
  ): Promise<void> {
    console.warn(`MCP服务器 ${error.serverId} 工具调用超时: ${error.message}`);
    
    // 工具超时通常不需要重启服务器，但需要监控频率
    const timeoutCount = this.getErrorCount(error.serverId, MCPErrorType.TOOL_TIMEOUT);
    
    if (timeoutCount > 5) {
      console.warn(`MCP服务器 ${error.serverId} 频繁超时，可能需要重启`);
      // 可以考虑重启服务器或调整超时设置
    }
  }

  /**
   * 处理工具执行错误
   */
  private async handleToolExecutionError(
    error: MCPError,
    server: MCPServerInstance
  ): Promise<void> {
    console.warn(`MCP服务器 ${error.serverId} 工具执行错误: ${error.message}`);
    
    // 工具执行错误通常是参数或环境问题，记录但不重启
    const errorCount = this.getErrorCount(error.serverId, MCPErrorType.TOOL_EXECUTION_ERROR);
    
    if (errorCount > 10) {
      console.warn(`MCP服务器 ${error.serverId} 频繁工具执行错误，可能需要检查配置`);
    }
  }

  /**
   * 处理进程崩溃
   */
  private async handleProcessCrash(
    error: MCPError,
    server: MCPServerInstance,
    retryCallback?: () => Promise<void>
  ): Promise<void> {
    console.error(`MCP服务器 ${error.serverId} 进程崩溃: ${error.message}`);
    
    server.status = 'error';
    server.error = `进程崩溃: ${error.message}`;
    
    const retryCount = this.getRetryCount(error.serverId);
    
    if (retryCount < this.defaultRetryConfig.maxRetries && retryCallback) {
      const delay = this.calculateRetryDelay(retryCount);
      console.log(`${delay}ms后尝试重启MCP服务器 ${error.serverId} (${retryCount + 1}/${this.defaultRetryConfig.maxRetries})`);
      
      this.scheduleRetry(error.serverId, delay, async () => {
        error.retryCount = retryCount + 1;
        await retryCallback();
      });
    } else {
      console.error(`MCP服务器 ${error.serverId} 重启失败，已达到最大重试次数`);
    }
  }

  /**
   * 处理通信错误
   */
  private async handleCommunicationError(
    error: MCPError,
    server: MCPServerInstance,
    retryCallback?: () => Promise<void>
  ): Promise<void> {
    console.warn(`MCP服务器 ${error.serverId} 通信错误: ${error.message}`);
    
    // 通信错误可能是临时的，短时间内重试
    const retryCount = this.getRetryCount(error.serverId);
    
    if (retryCount < 2 && retryCallback) {
      const delay = Math.min(1000 * (retryCount + 1), 5000);
      console.log(`${delay}ms后重试与MCP服务器 ${error.serverId} 的通信`);
      
      this.scheduleRetry(error.serverId, delay, async () => {
        error.retryCount = retryCount + 1;
        await retryCallback();
      });
    } else {
      console.error(`MCP服务器 ${error.serverId} 通信持续失败`);
      server.status = 'error';
      server.error = `通信失败: ${error.message}`;
    }
  }

  /**
   * 处理资源耗尽
   */
  private async handleResourceExhaustion(
    error: MCPError,
    server: MCPServerInstance
  ): Promise<void> {
    console.error(`MCP服务器 ${error.serverId} 资源耗尽: ${error.message}`);
    
    // 资源耗尽时，强制重启服务器
    if (server.process) {
      try {
        server.process.kill('SIGKILL');
      } catch (killError) {
        console.error(`强制终止MCP服务器进程失败:`, killError);
      }
    }
    
    server.status = 'stopped';
    server.error = `资源耗尽，已强制重启: ${error.message}`;
  }

  /**
   * 记录错误历史
   */
  private recordError(error: MCPError): void {
    if (!this.errorHistory.has(error.serverId)) {
      this.errorHistory.set(error.serverId, []);
    }
    
    const errors = this.errorHistory.get(error.serverId)!;
    errors.push(error);
    
    // 只保留最近100个错误
    if (errors.length > 100) {
      errors.splice(0, errors.length - 100);
    }
  }

  /**
   * 获取重试次数
   */
  private getRetryCount(serverId: string): number {
    const errors = this.errorHistory.get(serverId) || [];
    const recentErrors = errors.filter(
      err => Date.now() - err.timestamp.getTime() < 300000 // 5分钟内
    );
    
    return recentErrors.filter(
      err => err.type === MCPErrorType.STARTUP_FAILED || err.type === MCPErrorType.PROCESS_CRASHED
    ).length;
  }

  /**
   * 获取特定类型错误的数量
   */
  private getErrorCount(serverId: string, errorType: MCPErrorType): number {
    const errors = this.errorHistory.get(serverId) || [];
    const recentErrors = errors.filter(
      err => Date.now() - err.timestamp.getTime() < 300000 // 5分钟内
    );
    
    return recentErrors.filter(err => err.type === errorType).length;
  }

  /**
   * 计算重试延迟
   */
  private calculateRetryDelay(retryCount: number): number {
    const delay = this.defaultRetryConfig.baseDelay * 
                  Math.pow(this.defaultRetryConfig.backoffMultiplier, retryCount);
    return Math.min(delay, this.defaultRetryConfig.maxDelay);
  }

  /**
   * 调度重试
   */
  private scheduleRetry(serverId: string, delay: number, retryFn: () => Promise<void>): void {
    // 清除之前的重试计划
    const existingTimer = this.retrySchedules.get(serverId);
    if (existingTimer) {
      clearTimeout(existingTimer);
    }
    
    // 设置新的重试计划
    const timer = setTimeout(async () => {
      try {
        await retryFn();
      } catch (error) {
        console.error(`MCP服务器 ${serverId} 重试失败:`, error);
      } finally {
        this.retrySchedules.delete(serverId);
      }
    }, delay);
    
    this.retrySchedules.set(serverId, timer);
  }

  /**
   * 通知错误监听器
   */
  private notifyErrorListeners(error: MCPError): void {
    this.errorListeners.forEach(listener => {
      try {
        listener(error);
      } catch (listenerError) {
        console.error('错误监听器执行失败:', listenerError);
      }
    });
  }

  /**
   * 获取服务器错误历史
   */
  getErrorHistory(serverId: string): MCPError[] {
    return this.errorHistory.get(serverId) || [];
  }

  /**
   * 清理错误历史
   */
  clearErrorHistory(serverId?: string): void {
    if (serverId) {
      this.errorHistory.delete(serverId);
    } else {
      this.errorHistory.clear();
    }
  }

  /**
   * 取消所有重试计划
   */
  cancelAllRetries(): void {
    this.retrySchedules.forEach(timer => clearTimeout(timer));
    this.retrySchedules.clear();
  }

  /**
   * 清理资源
   */
  cleanup(): void {
    this.cancelAllRetries();
    this.errorHistory.clear();
    this.errorListeners.length = 0;
  }
}

// 导出单例
export const mcpErrorHandler = new MCPErrorHandler();